package com.xbongbong.workorder.service.impl;/*/*/

import com.alibaba.dingtalk.openapi.helper.Env;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.callback.help.ApiCallbackHelper;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.enums.DefaultTypeEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.OkHttpUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.RoleSimpleVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.WorkOrderErrorCodeEnum;
import com.xbongbong.pro.message.constant.WorkOrderPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.enums.SmsSendFromTypeEnum;
import com.xbongbong.pro.message.help.PushHelper;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.rabbitmq.producer.BaseProducer;
import com.xbongbong.pro.rabbitmq.producer.SmsProducer;
import com.xbongbong.pro.service.toolbox.elasticsearch.help.ProEsHelper;
import com.xbongbong.pro.sms.pojo.SmsReceiverPojo;
import com.xbongbong.pro.sms.pojo.dto.SmsRabbitMqDTO;
import com.xbongbong.pro.user.pojo.ReturnUserAndDepartmentPojo;
import com.xbongbong.pro.workorder.XbbShortUrlResponse;
import com.xbongbong.pro.workorder.pojo.CreateNodeReturnPojo;
import com.xbongbong.pro.workorder.pojo.TimeConsumingOutPojo;
import com.xbongbong.pro.workorder.pojo.dto.ChangeWorkflowDTO;
import com.xbongbong.saas.constant.workorder.WorkOrderConsueTimeConstant;
import com.xbongbong.saas.domain.entity.WorkOrderEntity;
import com.xbongbong.saas.domain.entity.WorkOrderEvaluateEntity;
import com.xbongbong.saas.domain.entity.WorkOrderFlowNodeEntity;
import com.xbongbong.saas.domain.entity.WorkOrderFlowUserEntity;
import com.xbongbong.saas.domain.entity.WorkOrderPersonEntity;
import com.xbongbong.saas.domain.entity.WorkOrderStageEntity;
import com.xbongbong.saas.domain.entity.WorkOrderTemplateEntity;
import com.xbongbong.saas.domain.entity.ext.ContactEntityExt;
import com.xbongbong.saas.domain.entity.ext.WorkOrderEntityExt;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.SmsSendTypeEnum;
import com.xbongbong.saas.enums.SmsTemplateSendApiEnum;
import com.xbongbong.saas.enums.WorkOrderFlowNodeTypeEnum;
import com.xbongbong.saas.enums.WorkOrderNodeStatusEnum;
import com.xbongbong.saas.enums.WorkOrderStageOperationEnum;
import com.xbongbong.saas.enums.WorkOrderStageRobTypeEnum;
import com.xbongbong.saas.enums.WorkOrderStageRuleEnum;
import com.xbongbong.saas.enums.WorkOrderStatusEnum;
import com.xbongbong.saas.enums.WorkOrderTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContactEnum;
import com.xbongbong.saas.enums.business.WorkOrderEnum;
import com.xbongbong.saas.model.ContactModel;
import com.xbongbong.saas.model.WorkOrderEvaluateModel;
import com.xbongbong.saas.model.WorkOrderFlowNodeModel;
import com.xbongbong.saas.model.WorkOrderModel;
import com.xbongbong.saas.model.WorkOrderPersonModel;
import com.xbongbong.saas.model.WorkOrderStageModel;
import com.xbongbong.saas.model.WorkOrderTemplateModel;
import com.xbongbong.saas.toolbox.help.TimeUtil;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.enums.RoleEnum;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workorder.service.WorkOrderBasicService;
import com.xbongbong.workorder.service.WorkOrderFlowUserService;
import com.xbongbong.workorder.service.WorkOrderStageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 *
 * @author 魏荣杰
 * @date 2019/3/30 16:02
 * @since v1.0
 * @version v1.0
 */
@Service("workOrderBasicService")
public class WorkOrderBasicServiceImpl implements WorkOrderBasicService {
    private static  final Logger LOG = LoggerFactory.getLogger(WorkOrderBasicServiceImpl.class);
    @Resource
    private WorkOrderStageModel workOrderStageModel;
    @Resource
    private WorkOrderFlowNodeModel workOrderFlowNodeModel;
    @Resource
    private WorkOrderPersonModel workOrderPersonModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private UserModel userModel;
    @Resource
    private WorkOrderModel workOrderModel;
    @Resource
    private WorkOrderFlowUserService workOrderFlowUserService;
    @Resource
    private WorkOrderTemplateModel workOrderTemplateModel;
    @Resource
    private WorkOrderStageService workOrderStageService;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private PushHelper pushHelper;
    @Resource
    private BaseProducer baseProducer;
    @Resource
    private ProEsHelper proEsHelper;
    @Resource
    private ContactModel contactModel;
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private SmsProducer smsProducer;
    @Resource
    private WorkOrderEvaluateModel workOrderEvaluateModel;
    @Resource
    private ApiCallbackHelper apiCallbackHelper;

    @Override
    public List<String> getServiceUserIdList(String corpid, String refRobId) {
        List<String> userIdList = new ArrayList<>();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("tagIdJsonLike", Long.valueOf(refRobId));
        param.put("del", 0);
        List<WorkOrderPersonEntity> personEntityList = workOrderPersonModel.findEntitys(param);
        for (WorkOrderPersonEntity entity : personEntityList) {
            userIdList.add(entity.getUserId());
        }
        return userIdList;
    }

    @Override
    public List<String> getDepartmentUserIdList(String corpid, String refRobId) {
        List<String> userIdList = new ArrayList<>();
        List<Long> userDepartmentList = Collections.singletonList(Long.valueOf(refRobId));
        //是否为全公司
        Boolean isTopDep = userDepartmentList.contains(1L);
        Set<Long> depSet = new HashSet<>();
        if (!isTopDep){
            depSet.addAll(departmentModel.getSubDepIdList(corpid, userDepartmentList));
        }
        if (isTopDep) {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("del", 0);
            userIdList = userModel.getUserIds(param);
        } else {
            userIdList = userModel.getDepUserIdList(corpid, depSet);
        }
        return userIdList;
    }

    @Override
    public CreateNodeReturnPojo createNode(WorkOrderEntity workOrderEntity, WorkOrderTemplateEntity workOrderTemplateEntity, WorkOrderStageEntity workOrderStageEntity) throws XbbException {
        String corpid = workOrderEntity.getCorpid();
        Long workOrderId = workOrderEntity.getId();
        Integer expectedTime = workOrderTemplateEntity.getExpectedTime();
        Boolean ifFree = Objects.equals(workOrderTemplateEntity.getIsFree(),1);
        Set<String> pushIdList = new HashSet<>();
        String userId = null;
        WorkOrderFlowNodeEntity workOrderFlowNodeEntity;
        boolean isRob = false;
        if (ifFree) {
            JSONObject dataJsonObj = workOrderEntity.getData();
            String managerId = dataJsonObj.getString(WorkOrderEnum.MANAGER_ID.getAttr());
            UserEntity userEntity = userModel.getByKey(managerId, corpid);
            if (userEntity == null) {
                throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222027);
            }
            //自由流程，直接根据前端选择的负责人生成node
            workOrderFlowNodeEntity = createNormalNode(workOrderId,expectedTime,userEntity,null);
            userId = userEntity.getUserId();
            pushIdList.add(userId);
        } else {
            //指定流程
            WorkOrderStageRuleEnum workOrderStageRuleEnum = WorkOrderStageRuleEnum.getByCode(workOrderStageEntity.getRuleId());
            expectedTime = workOrderStageEntity.getExpectedTime();
            if (workOrderStageRuleEnum == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            WorkOrderStageRobTypeEnum workOrderStageRobTypeEnum = WorkOrderStageRobTypeEnum.getByCode(workOrderStageEntity.getRefRobType());
            if (workOrderStageRobTypeEnum == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            switch (workOrderStageRuleEnum) {
                case SEND_TO_CLOSE:
                    params.put("corpid", corpid);
                    params.put("del", DelEnum.NORMAL.getDel());
                    params.put("tagIdJsonLike", Long.valueOf(workOrderStageEntity.getRefRobId()));
                    List<WorkOrderPersonEntity> personList = workOrderPersonModel.findEntitys(params);
                    if (personList == null || personList.size() ==  0) {
                        throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222014.getCode(), WorkOrderErrorCodeEnum.API_ERROR_222014.getMsg(), I18nMessageUtil.getMessage(I18nStringConstant.SERVICE));
                    }
                    //筛选最近的服务人员
                    JSONObject dataJsonObj = workOrderEntity.getData();
                    if (Objects.isNull(dataJsonObj)) {
                        throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222060);
                    }
                    JSONObject addressJsonObj = dataJsonObj.getJSONObject(WorkOrderEnum.ADDRESS.getAttr());
                    JSONObject locationJsonObj = null;
                    if (Objects.nonNull(addressJsonObj)) {
                        locationJsonObj = addressJsonObj.getJSONObject("location");
                    }
                    Double lon = 0D;
                    Double lat = 0D;
                    Double beeline = Double.MAX_VALUE;
                    if (locationJsonObj != null) {
                        lon = locationJsonObj.getDouble("lon");
                        lat = locationJsonObj.getDouble("lat");
                    }
                    WorkOrderPersonEntity workOrderPersonEntity = new WorkOrderPersonEntity();
                    for (WorkOrderPersonEntity personEntity : personList) {
                        Double distance = Math.pow(lon - personEntity.getLongitude(), 2) + Math.pow(lat - personEntity.getLatitude(), 2);
                        if (distance < beeline) {
                            workOrderPersonEntity = personEntity;
                            beeline = distance;
                        }
                    }
                    UserEntity userEntity = userModel.getByKey(workOrderPersonEntity.getUserId(),corpid);
                    if (userEntity == null) {
                        throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222027);
                    }
                    workOrderFlowNodeEntity = createNormalNode(workOrderId,expectedTime,userEntity,workOrderStageEntity);
                    userId = workOrderPersonEntity.getUserId();
                    pushIdList.add(userId);
                    break;
                case SEND_TO_LESS:
                    List<String> userIdList = new ArrayList<>();
                    String robTypeStr = workOrderStageRobTypeEnum.getName();
                    switch (workOrderStageRobTypeEnum) {
                        case USER:
                            break;
                        case SERVICE:
                            userIdList = getServiceUserIdList(corpid, workOrderStageEntity.getRefRobId());
                            break;
                        case DEPARTMENT:
                            userIdList = getDepartmentUserIdList(corpid, workOrderStageEntity.getRefRobId());
                            break;
                        default:
                            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                    }
                    if (userIdList.isEmpty()) {
                        throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222014.getCode(), String.format(WorkOrderErrorCodeEnum.API_ERROR_222014.getMsg(), robTypeStr));
                    }
                    params.put("corpid", corpid);
                    params.put("del", 0);
                    params.put("isNow", 1);
                    params.put("userIdIn", userIdList);
                    params.put("statusIn", Arrays.asList(WorkOrderNodeStatusEnum.UNACCEPTED.getCode(), WorkOrderNodeStatusEnum.ONGOING.getCode()));
                    params.put("groupByStr", "user_id");
                    params.put("orderByStr", "count(*) asc");
                    List<String> nodeUserIdList = workOrderFlowNodeModel.getUserIdList(params);
                    userIdList.removeAll(nodeUserIdList);
                    if (userIdList.isEmpty()) {
                        userId = nodeUserIdList.get(0);
                    } else {
                        userId = userIdList.get(0);
                    }
                    userEntity = userModel.getByKey(userId, corpid);
                    if (userEntity == null) {
                        throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222027);
                    }
                    workOrderFlowNodeEntity = createNormalNode(workOrderId,expectedTime,userEntity,workOrderStageEntity);
                    pushIdList.add(userId);
                    break;
                case ROB:
                    isRob = true;
                    //如果是抢单就先生成节点，待人抢单后更新node数据
                    workOrderFlowNodeEntity = createRobNode(workOrderEntity, expectedTime,workOrderStageEntity);
                    switch (workOrderStageRobTypeEnum) {
                        case USER:
                            break;
                        case SERVICE:
                            pushIdList.addAll(getServiceUserIdList(corpid, workOrderStageEntity.getRefRobId()));
                            break;
                        case DEPARTMENT:
                            pushIdList.addAll(getDepartmentUserIdList(corpid, workOrderStageEntity.getRefRobId()));
                            break;
                        default:
                            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                    }
                    break;
                default:
                    //选择了人
                    userEntity = new UserEntity();
                    BeanUtil.copyProperties(workOrderStageEntity,userEntity);
                    userEntity.setUserId(workOrderStageEntity.getRefRobId());
                    userEntity.setAvatar(workOrderStageEntity.getUserAvatar());
                    userEntity.setName(workOrderStageEntity.getRefRobName());
                    userEntity.setCorpid(workOrderStageEntity.getCorpid());
                    workOrderFlowNodeEntity = createNormalNode(workOrderId,expectedTime,userEntity,workOrderStageEntity);
                    pushIdList.add(workOrderStageEntity.getRefRobId());
                    userId = workOrderStageEntity.getRefRobId();
            }
        }

        return new CreateNodeReturnPojo(pushIdList, userId, workOrderFlowNodeEntity, isRob);
    }

    /**
     * 新建抢单节点
     * @param workOrderEntity 工单
     * @param expectedTime 预计耗时
     * @param workOrderStageEntity 阶段
     */
    private WorkOrderFlowNodeEntity createRobNode(WorkOrderEntity workOrderEntity, Integer expectedTime, WorkOrderStageEntity workOrderStageEntity) throws XbbException{
        WorkOrderFlowNodeEntity workOrderFlowNodeEntity = new WorkOrderFlowNodeEntity();
        workOrderFlowNodeEntity.setCorpid(workOrderStageEntity.getCorpid());
        workOrderFlowNodeEntity.setWorkOrderId(workOrderEntity.getId());
        workOrderFlowNodeEntity.setUserId("");
        workOrderFlowNodeEntity.setUserAvatar("");
        workOrderFlowNodeEntity.setUserName("");
        workOrderFlowNodeEntity.setStageId(workOrderStageEntity.getId());
        workOrderFlowNodeEntity.setStageName(workOrderStageEntity.getName());
        workOrderFlowNodeEntity.setStatus(WorkOrderNodeStatusEnum.UNACCEPTED.getCode());
        Integer maxSort = getMaxSort(workOrderFlowNodeEntity.getWorkOrderId(),workOrderFlowNodeEntity.getStageId(),workOrderFlowNodeEntity.getCorpid());
        workOrderFlowNodeEntity.setSort(maxSort);
        workOrderFlowNodeEntity.setIsNow(1);
        workOrderFlowNodeEntity.setExpectedTime(expectedTime);
        workOrderFlowNodeEntity.setActualTime(0);
        workOrderFlowNodeEntity.setStartTime(0L);
        workOrderFlowNodeEntity.setEndTime(0L);
        //设置为抢单节点
        workOrderFlowNodeEntity.setRobId(workOrderStageEntity.getRefRobId());
        workOrderFlowNodeEntity.setRobType(workOrderStageEntity.getRefRobType());
        workOrderFlowNodeEntity.setNodeType(WorkOrderFlowNodeTypeEnum.ROB_NODE.getCode());

        //更新工单主表的type为抢单工单
//        workOrderEntity.setType(WorkOrderTypeEnum.ROB.getCode());
//        workOrderModel.save(workOrderEntity);

        return workOrderFlowNodeEntity;
    }

    /**
     * 新建普通节点
     * @param workOrderId 工单id
     * @param expectedTime 预计耗时
     * @param userEntity 节点负责人
     * @param workOrderStageEntity 阶段，自由流程null
     */
    private WorkOrderFlowNodeEntity createNormalNode(Long workOrderId, Integer expectedTime, UserEntity userEntity, WorkOrderStageEntity workOrderStageEntity) throws XbbException{
        WorkOrderFlowNodeEntity workOrderFlowNodeEntity = new WorkOrderFlowNodeEntity();
        workOrderFlowNodeEntity.setCorpid(userEntity.getCorpid());
        workOrderFlowNodeEntity.setWorkOrderId(workOrderId);
        workOrderFlowNodeEntity.setUserId(userEntity.getUserId());
        workOrderFlowNodeEntity.setUserAvatar(userEntity.getAvatar());
        workOrderFlowNodeEntity.setUserName(userEntity.getName());
        workOrderFlowNodeEntity.setStatus(WorkOrderNodeStatusEnum.UNACCEPTED.getCode());
//        workOrderFlowNodeEntity.setSort(0);
        workOrderFlowNodeEntity.setIsNow(1);
        workOrderFlowNodeEntity.setExpectedTime(expectedTime);
        workOrderFlowNodeEntity.setActualTime(0);
        workOrderFlowNodeEntity.setStartTime(0L);
        workOrderFlowNodeEntity.setEndTime(0L);
        if (!Objects.isNull(workOrderStageEntity)){
            workOrderFlowNodeEntity.setStageId(workOrderStageEntity.getId());
            workOrderFlowNodeEntity.setStageName(workOrderStageEntity.getName());
        }
        Integer maxSort = getMaxSort(workOrderFlowNodeEntity.getWorkOrderId(),workOrderFlowNodeEntity.getStageId(),workOrderFlowNodeEntity.getCorpid());
        workOrderFlowNodeEntity.setSort(maxSort);
        return workOrderFlowNodeEntity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeWorkflow(ChangeWorkflowDTO changeWorkflowDTO) throws XbbException {
        Long workOrderId = changeWorkflowDTO.getWorkOrderId();
        String corpid = changeWorkflowDTO.getCorpid();

        WorkOrderEntity workOrderEntity = workOrderModel.getByKey(workOrderId, corpid);
        if (workOrderEntity == null || Objects.equals(workOrderEntity.getDel(), DelEnum.DELETE.getDel())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }

        WorkOrderEntity oldWorkOrderEntity = new WorkOrderEntity();
        try {
            WorkOrderStageOperationEnum workOrderStageOperationEnum = WorkOrderStageOperationEnum.getByAlias(changeWorkflowDTO.getOperate());
            List<WorkOrderFlowNodeEntity> workOrderFlowNodeEntityList = workOrderFlowNodeModel.getNode(workOrderId,1,corpid);
            WorkOrderFlowNodeEntity nowNodeEntity = workOrderFlowNodeEntityList.get(0);
            oldWorkOrderEntity = (WorkOrderEntity) CloneUtil.deepClone(workOrderEntity);
            switch (workOrderStageOperationEnum){
                case ACCEPT:
                    accept(changeWorkflowDTO, nowNodeEntity, workOrderEntity);
                    break;
                case COMPLETE:
                    complete(changeWorkflowDTO, nowNodeEntity, workOrderEntity);
                    break;
                case CLOSE:
                    close(changeWorkflowDTO, nowNodeEntity, workOrderEntity);
                    break;
                case ROLLBACK:
                    rollback(changeWorkflowDTO, nowNodeEntity, workOrderEntity);
                    break;
                case TRANSFER:
                    transfer(changeWorkflowDTO, nowNodeEntity, workOrderEntity);
                    break;
                case RESTART:
                    restart(changeWorkflowDTO, nowNodeEntity, workOrderEntity);
                    break;
                default:
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            apiCallbackHelper.callback4Special(changeWorkflowDTO.getCorpid(), SaasMarkEnum.SAAS.getCode(),
                    changeWorkflowDTO.getWorkOrderId(), OperateTypeEnum.EDIT, XbbRefTypeEnum.WORK_ORDER);
        } catch (XbbException e) {
            proEsHelper.reductionEsInUpdate(oldWorkOrderEntity, workOrderId, corpid, IndexTypeEnum.IDX_SAAS_WORK_ORDER);
            throw e;
        } catch (Exception e) {
            LOG.error("WorkOrderBasicServiceImpl.changeWorkflow error", e);
            proEsHelper.reductionEsInUpdate(oldWorkOrderEntity, workOrderId, corpid, IndexTypeEnum.IDX_SAAS_WORK_ORDER);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    private void restart(ChangeWorkflowDTO changeWorkflowDTO, WorkOrderFlowNodeEntity nowNodeEntity, WorkOrderEntity workOrderEntity) throws XbbException {
        Long workOrderId = workOrderEntity.getId();
        String corpid = workOrderEntity.getCorpid();
        Long templateId = workOrderEntity.getTemplateId();
        Long currentTime = DateTimeUtil.getInt();
        WorkOrderStageEntity workOrderStageEntity;
        WorkOrderTemplateEntity workOrderTemplateEntity;
        boolean isFree;
        UserEntity userEntity;//当前阶段信息
        //自由指派第一节点或指定流程第一阶段第一节点
        workOrderTemplateEntity = workOrderTemplateModel.getBykey(templateId,corpid);
        isFree = workOrderTemplateEntity.getIsFree() == 1;
        String mainUserId = null;
        workOrderFlowNodeModel.save(createRestartTagNode(changeWorkflowDTO, nowNodeEntity));
        Boolean isRob = false;
        String stageName = "";
        List<String> robPushUserIds = new ArrayList<>();
        if (isFree) {
            String userId = (String) ProSaveHelp.getId(JSONObject.parseObject(JSON.toJSONString(changeWorkflowDTO.getUser())));
            userEntity = userModel.getByKey(userId, corpid);
            if (Objects.nonNull(userEntity)) {
                WorkOrderFlowNodeEntity node = createNormalNode(workOrderId, workOrderTemplateEntity.getExpectedTime(), userEntity, null);
                workOrderFlowNodeModel.save(node);
                mainUserId = node.getUserId();
            } else {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100065);
            }
        } else {
            workOrderStageEntity = workOrderStageModel.getByKey(Long.valueOf(changeWorkflowDTO.getNextStageId().getValue().toString()),corpid);
            stageName = workOrderStageEntity.getName();
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid",corpid);
            param.put("workOrderId",workOrderId);
            param.put("stageId",changeWorkflowDTO.getNextStageId().getValue());
            param.put("del",0);
            param.put("orderByStr", "add_time desc");
            List<WorkOrderFlowNodeEntity> historyNodelist = workOrderFlowNodeModel.findEntitys(param);
            if (historyNodelist.isEmpty()){
                workOrderTemplateEntity = workOrderTemplateModel.getBykey(workOrderEntity.getTemplateId(),corpid);
                CreateNodeReturnPojo createNodeReturnPojo = createNode(workOrderEntity,workOrderTemplateEntity,workOrderStageEntity);
                WorkOrderFlowNodeEntity nodeEntity = createNodeReturnPojo.getWorkOrderFlowNodeEntity();
//                nodeEntity.setMemo(changeWorkflowDTO.getMemo());
                workOrderFlowNodeModel.save(nodeEntity);
                workOrderEntity.setNowStageId(workOrderStageEntity.getId());
                mainUserId = nodeEntity.getUserId();
                isRob = createNodeReturnPojo.getIsRob();
                robPushUserIds = new ArrayList<>(createNodeReturnPojo.getPushIdList());
            } else {
                WorkOrderFlowNodeEntity flowNodeEntity = historyNodelist.get(0);
//                flowNodeEntity.setMemo(changeWorkflowDTO.getMemo());
                Long stageId = flowNodeEntity.getStageId();
                WorkOrderStageEntity workOrderStageEntity1 = workOrderStageModel.getByKey(stageId, corpid);
                if (Objects.equals(workOrderStageEntity1.getRuleId(), WorkOrderStageRuleEnum.ROB.getCode())) {
                    flowNodeEntity.setUserId("");
                    flowNodeEntity.setUserAvatar("");
                    flowNodeEntity.setUserName("");
                    flowNodeEntity.setNodeType(WorkOrderFlowNodeTypeEnum.ROB_NODE.getCode());
                    flowNodeEntity.setRobId(workOrderStageEntity1.getRefRobId());
                    flowNodeEntity.setRobType(workOrderStageEntity1.getRefRobType());
                }
                workOrderFlowNodeModel.save(createRestartNode(flowNodeEntity));
                if (Objects.equals(flowNodeEntity.getNodeType(), WorkOrderFlowNodeTypeEnum.ROB_NODE.getCode()) && flowNodeEntity.getUserId().isEmpty()) {
                    //抢单节点没人抢单就关闭，然后重启的特殊情况处理
                    isRob = true;
                }
                mainUserId = flowNodeEntity.getUserId();
                workOrderEntity.setNowStageId(flowNodeEntity.getStageId());
            }
        }
        nowNodeEntity.setIsNow(0);
        workOrderFlowNodeModel.save(nowNodeEntity);
        workOrderEntity.setStatus(WorkOrderStatusEnum.UNACCEPTED.getCode());
        workOrderEntity.setStartTime(0L);
        workOrderEntity.setEndTime(0L);
        workOrderEntity.setCloseTime(0L);
        workOrderEntity.setActualTime(0);
        workOrderEntity.setUpdateTime(currentTime);
        if (isRob) {
            workOrderEntity.setType(WorkOrderTypeEnum.ROB.getCode());
        }
        JSONObject data = workOrderEntity.getData();
        data.put(WorkOrderEnum.NODE_STATUS.getAttr(), WorkOrderStatusEnum.UNACCEPTED.getCode());
        //阶段名称
        if (!Objects.equals(stageName, "")){
            data.put(WorkOrderEnum.STAGE_NAME.getAttr(), stageName);
        }
        workOrderEntity.setData(data);
        workOrderModel.save(workOrderEntity);

        //更新团队
        List<WorkOrderFlowUserEntity> workOrderFlowUserEntities = workOrderFlowUserService.getTeamUserList(workOrderId, corpid);
        List<String> coUserId = new ArrayList<>();
        for (WorkOrderFlowUserEntity entity : workOrderFlowUserEntities) {
            coUserId.add(entity.getUserId());
        }
        if (isRob) {
            mainUserId = null;
        }
        workOrderFlowUserService.changeTeamInFlow(mainUserId, coUserId, corpid, workOrderId);

        //工单重启消息推送
        UserVO loginUser = changeWorkflowDTO.getLoginUser();
        List<String> pushUserIds = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.WORKORDER_RESTART.getCode(), PushTypeEnum.WORKORDER_RESTART.getSubCode(), loginUser, workOrderEntity);
        PushRefTypePojo.Options options = new PushRefTypePojo.Options(workOrderEntity.getAppId(), workOrderEntity.getMenuId(), workOrderEntity.getFormId(), workOrderEntity.getId(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_ORDER.getCode());
        String pushMsg = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_RESTART), workOrderEntity.getSerialNo(), changeWorkflowDTO.getMemo(), loginUser.getName());
        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserIds, Collections.singletonList(workOrderEntity.getId()), 0, null, I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_RESTART_TITLE), pushMsg, null, options);
        baseProducer.sendMessage(PushTypeEnum.WORKORDER_RESTART, messageRabbitMqDTO);

        if (isRob) {
            //如果重启到抢单节点，需要发送待抢单消息
            pushMsg = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_TO_ROB), workOrderEntity.getSerialNo(), stageName);
            messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, robPushUserIds, Collections.singletonList(workOrderId), 0, null, I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_WAIT_ROB_TITLE), pushMsg, null, options);
            baseProducer.sendMessage(PushTypeEnum.WORKORDER_PUSH, messageRabbitMqDTO);
        }
    }

    private WorkOrderFlowNodeEntity createRestartTagNode(ChangeWorkflowDTO changeWorkflowDTO, WorkOrderFlowNodeEntity nowNodeEntity) {
        WorkOrderFlowNodeEntity workOrderFlowNodeEntity = new WorkOrderFlowNodeEntity();
        UserVO userVO = changeWorkflowDTO.getLoginUser();
        workOrderFlowNodeEntity.setCorpid(changeWorkflowDTO.getCorpid());
        workOrderFlowNodeEntity.setUserId(userVO.getUserId());
        workOrderFlowNodeEntity.setUserName(userVO.getName());
        workOrderFlowNodeEntity.setUserAvatar(userVO.getAvatar());
        workOrderFlowNodeEntity.setWorkOrderId(changeWorkflowDTO.getWorkOrderId());
        workOrderFlowNodeEntity.setStatus(WorkOrderNodeStatusEnum.RESTART.getCode());
        workOrderFlowNodeEntity.setStageName(WorkOrderNodeStatusEnum.RESTART.getName());

        workOrderFlowNodeEntity.setStageId(nowNodeEntity.getStageId());
        workOrderFlowNodeEntity.setMemo(changeWorkflowDTO.getMemo());
        workOrderFlowNodeEntity.setStartTime(DateTimeUtil.getInt());
        workOrderFlowNodeEntity.setAddTime(DateTimeUtil.getInt());
        workOrderFlowNodeEntity.setUpdateTime(DateTimeUtil.getInt());
        workOrderFlowNodeEntity.setSort(0);
        return workOrderFlowNodeEntity;
    }

    private void transfer(ChangeWorkflowDTO changeWorkflowDTO, WorkOrderFlowNodeEntity nowNodeEntity, WorkOrderEntity workOrderEntity) throws XbbException {
        Long workOrderId = workOrderEntity.getId();
        String corpid = workOrderEntity.getCorpid();
        Long templateId = workOrderEntity.getTemplateId();
        Long currentTime = DateTimeUtil.getInt();
        boolean flag;
        Long stageId;
        WorkOrderTemplateEntity workOrderTemplateEntity;
        boolean isFree;
        WorkOrderStageEntity workOrderStageEntity;
        Integer actualTime;
        UserEntity userEntity;
        flag = nowNodeEntity.getStatus().equals(WorkOrderNodeStatusEnum.ONGOING.getCode());
        if (!flag){
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222015);
        }
        //是否自由指派
        stageId = nowNodeEntity.getStageId();
        workOrderTemplateEntity = workOrderTemplateModel.getBykey(templateId,corpid);
        isFree = workOrderTemplateEntity.getIsFree() == 1;
        workOrderStageEntity = null;
        String stageName = "";
        if (!isFree) {
            workOrderStageEntity = workOrderStageModel.getByKey(stageId, corpid);
            if (workOrderStageEntity.getDel() == 1) {
                throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222025);
            }
            stageName = workOrderStageEntity.getName();
        }
        actualTime = (int)(currentTime - nowNodeEntity.getStartTime());
        nowNodeEntity.setMemo(changeWorkflowDTO.getMemo());
        nowNodeEntity.setEndTime(currentTime);
        nowNodeEntity.setActualTime(actualTime);
        nowNodeEntity.setIsNow(0);
        nowNodeEntity.setStatus(WorkOrderNodeStatusEnum.TRANSFERRED.getCode());
        nowNodeEntity.setUpdateTime(currentTime);
        nowNodeEntity.setEndOperatorName(Objects.equals(nowNodeEntity.getUserId(),changeWorkflowDTO.getUserId()) ? "" : changeWorkflowDTO.getLoginUserName());
        //状态更新
        workOrderFlowNodeModel.update(nowNodeEntity);
        workOrderEntity.setUpdateTime(currentTime);
        JSONObject data = workOrderEntity.getData();
        data.put(WorkOrderEnum.NODE_STATUS.getAttr(), WorkOrderNodeStatusEnum.UNACCEPTED.getCode());
        //阶段名称
        if (!Objects.equals(stageName, "")) {
            data.put(WorkOrderEnum.STAGE_NAME.getAttr(), stageName);
        }
        workOrderEntity.setData(data);

        String mainUserId = (String) ProSaveHelp.getId(JSONObject.parseObject(JSON.toJSONString(changeWorkflowDTO.getUser())));
        userEntity = userModel.getByKey(mainUserId, corpid);
        if (Objects.isNull(userEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004);
        }
        WorkOrderFlowNodeEntity workOrderFlowNodeEntity = createNormalNode(workOrderId,0,userEntity,workOrderStageEntity);
        workOrderFlowNodeEntity.setSort(nowNodeEntity.getSort() + 1);
        workOrderFlowNodeModel.save(workOrderFlowNodeEntity);
        //更新协同人团队
        List<String> coUserId = new ArrayList<>();
        List<Object> idList = ProSaveHelp.getIdList(JSONArray.parseArray(JSON.toJSONString(changeWorkflowDTO.getCoUser())));
        for (Object id : idList) {
            coUserId.add((String) id);
        }
        workOrderFlowUserService.changeTeamInFlow(mainUserId, coUserId, corpid, workOrderId);

        workOrderEntity.setNowStageId(workOrderFlowNodeEntity.getStageId());
        workOrderEntity.setStatus(WorkOrderStatusEnum.UNACCEPTED.getCode());
        workOrderModel.update(workOrderEntity);

        //工单转派消息推送
        UserVO loginUser = changeWorkflowDTO.getLoginUser();
        List<String> pushUserIds = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.WORKORDER_TRANSFER.getCode(), PushTypeEnum.WORKORDER_TRANSFER.getSubCode(), loginUser, workOrderEntity);
        String pushMsg;
        if (isFree) {
            pushMsg = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_TO_ACCEPT_FREE), workOrderEntity.getSerialNo());
        } else {
            pushMsg = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_TO_ACCEPT), workOrderEntity.getSerialNo(), stageName);
        }

        PushRefTypePojo.Options options = new PushRefTypePojo.Options(workOrderEntity.getAppId(), workOrderEntity.getMenuId(), workOrderEntity.getFormId(), workOrderEntity.getId(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_ORDER.getCode());
        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserIds, Collections.singletonList(workOrderId), 0, null, I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_TRANSFER_TITLE), pushMsg, null, options);
        baseProducer.sendMessage(PushTypeEnum.WORKORDER_TRANSFER, messageRabbitMqDTO);

    }

    private void rollback(ChangeWorkflowDTO changeWorkflowDTO, WorkOrderFlowNodeEntity nowNodeEntity, WorkOrderEntity workOrderEntity) throws XbbException {
        Long workOrderId = workOrderEntity.getId();
        String corpid = workOrderEntity.getCorpid();
        Long templateId = workOrderEntity.getTemplateId();
        Long currentTime = DateTimeUtil.getInt();
        boolean flag;
        Long stageId;
        Integer actualTime;
        WorkOrderTemplateEntity workOrderTemplateEntity;
        boolean isFree;
        WorkOrderStageEntity workOrderStageEntity;
        boolean isFirst;
        flag = nowNodeEntity.getStatus().equals(WorkOrderNodeStatusEnum.ONGOING.getCode());
        if (!flag){
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222015);
        }
        Integer sort = nowNodeEntity.getSort();
        stageId = nowNodeEntity.getStageId();

        Long nodeStartTime = nowNodeEntity.getStartTime();
        actualTime = (int)(currentTime - nodeStartTime);
        //回退原id
        Long sourceId = nowNodeEntity.getSourceId();
        //如果回退原id不等于，即说明当前节点是回退后生成的，需要查找原节点位置
        if (sourceId != 0){
            WorkOrderFlowNodeEntity souceNode = workOrderFlowNodeModel.getByKey(sourceId,corpid);
            sort = souceNode.getSort();
        }
        workOrderTemplateEntity = workOrderTemplateModel.getBykey(templateId,corpid);
        isFree = workOrderTemplateEntity.getIsFree() == 1;
        //工作流模板阶段
        Integer stageSort = 0;
        boolean stageWrong = false;
        String stageName = "";
        if (!isFree) {
            workOrderStageEntity = workOrderStageModel.getByKey(stageId,corpid);
            if(workOrderStageEntity==null){
                throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222045);
            }
            if (workOrderStageEntity.getDel() == 1){
                stageWrong = true;
                stageSort = -1;
            }else {
                stageSort = workOrderStageEntity.getSort();
            }
            isFirst = Objects.equals(stageSort,0) && nowNodeEntity.getSort().equals(0);
            stageName = workOrderStageEntity.getName();
        }else {
            isFirst = nowNodeEntity.getSort().equals(0);
        }
        if (isFirst){
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222004);
        }
        //回退的上个结点负责人
        String preMainUserId = "";
        String preMainUserName;
        if (stageWrong){
            WorkOrderStageEntity fisrtStageEntity = workOrderStageService.getFirstStage(workOrderEntity.getTemplateId(),corpid);
            CreateNodeReturnPojo createNodeReturnPojo = createNode(workOrderEntity,workOrderTemplateEntity,fisrtStageEntity);
            WorkOrderFlowNodeEntity workOrderFlowNodeEntity = createNodeReturnPojo.getWorkOrderFlowNodeEntity();
            workOrderFlowNodeModel.save(workOrderFlowNodeEntity);
            if (createNodeReturnPojo.getIsRob()) {
                workOrderEntity.setType(WorkOrderTypeEnum.ROB.getCode());
            }
            preMainUserId = workOrderFlowNodeEntity.getUserId();
            preMainUserName = workOrderFlowNodeEntity.getUserName();
        }else {
            WorkOrderFlowNodeEntity preNodeEntity;
            if (isFree){
                Map<String,Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                params.put("corpid",corpid);
                params.put("workOrderId",workOrderId);
                params.put("nowSort",sort);
                params.put("del",0);
                preNodeEntity = workOrderFlowNodeModel.getPrevNode(params);
            }else {
                if (Objects.equals(sort,0)){
                    WorkOrderStageEntity preStage = workOrderStageService.getPreStage(templateId,nowNodeEntity.getStageId(),corpid);
                    List<Long> preStageList = workOrderStageService.getPreStageList(templateId,nowNodeEntity.getStageId(),corpid);
                    preNodeEntity = workOrderFlowNodeModel.getLastNodeByStageList(workOrderId,preStageList,corpid);
                    if (Objects.isNull(preNodeEntity)){
                        throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222004);
                    }
                }else {
                    Map<String,Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    params.put("corpid",corpid);
                    params.put("workOrderId",workOrderId);
                    params.put("stageId",nowNodeEntity.getStageId());
                    params.put("nowSort",sort);
                    params.put("del",0);
                    preNodeEntity = workOrderFlowNodeModel.getPrevNode(params);

                }
            }
//                    Map<String,Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//                    params.put("corpid",corpid);
//                    params.put("workOrderId",workOrderId);
//                    params.put("nowSort",sort);
//                    params.put("del",0);
//                    WorkOrderFlowNodeEntity preNodeEntity = workOrderFlowNodeModel.getPrevNode(params);
            if (!Objects.equals(preNodeEntity.getStageId(),stageId)){
                workOrderEntity.setNowStageId(preNodeEntity.getStageId());
            }
            sourceId = preNodeEntity.getId();
            WorkOrderFlowNodeEntity workOrderFlowNodeEntity = createRollbackNode(preNodeEntity);
            workOrderFlowNodeEntity.setSourceId(sourceId);
            workOrderFlowNodeModel.save(workOrderFlowNodeEntity);
            preMainUserId = workOrderFlowNodeEntity.getUserId();
            preMainUserName = workOrderFlowNodeEntity.getUserName();
            //如果回退的上一个节点是抢单节点，把工单类型改成抢单类型
            if (Objects.equals(workOrderFlowNodeEntity.getNodeType(), 1) && Objects.equals(preMainUserId, "")) {
                workOrderEntity.setType(1);
            }
        }

        workOrderEntity.setUpdateTime(currentTime);
        //工作流更新
        JSONObject data = workOrderEntity.getData();
        data.put(WorkOrderEnum.NODE_STATUS.getAttr(), WorkOrderNodeStatusEnum.ROLLBACK.getCode());
        //阶段名称
        if (!Objects.equals(nowNodeEntity.getStageName(), "") && nowNodeEntity.getStageName() != null) {
            data.put(WorkOrderEnum.STAGE_NAME.getAttr(), nowNodeEntity.getStageName());
        }
        workOrderEntity.setData(data);
        workOrderModel.save(workOrderEntity);
        nowNodeEntity.setMemo(changeWorkflowDTO.getMemo());
        nowNodeEntity.setStatus(WorkOrderNodeStatusEnum.ROLLBACK.getCode());
        nowNodeEntity.setEndTime(currentTime);
        nowNodeEntity.setActualTime(actualTime);
        nowNodeEntity.setIsNow(0);
        nowNodeEntity.setUpdateTime(currentTime);
        nowNodeEntity.setEndOperatorName(Objects.equals(nowNodeEntity.getUserId(),changeWorkflowDTO.getUserId()) ? "" : changeWorkflowDTO.getLoginUserName());
        //状态更新
        workOrderFlowNodeModel.update(nowNodeEntity);

        //更新协同人团队,回退到上个节点
        List<WorkOrderFlowUserEntity> workOrderFlowUserEntities = workOrderFlowUserService.getTeamUserList(workOrderId, corpid);
        List<String> coUserId = new ArrayList<>();
        for (WorkOrderFlowUserEntity entity : workOrderFlowUserEntities) {
            coUserId.add(entity.getUserId());
        }
        workOrderFlowUserService.changeTeamInFlow(preMainUserId, coUserId, corpid, workOrderId);


        //工单回退消息
        UserVO loginUser = changeWorkflowDTO.getLoginUser();
        List<String> pushUserIds = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.WORKORDER_ROLLBACK.getCode(), PushTypeEnum.WORKORDER_ROLLBACK.getSubCode(), loginUser, workOrderEntity);
        String pushMsg;
        if (isFree) {
            pushMsg = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_ROLL_BACK_FREE), preMainUserName, workOrderEntity.getSerialNo());
        } else {
            pushMsg = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_ROLL_BACK), preMainUserName, workOrderEntity.getSerialNo(), stageName);
        }

        PushRefTypePojo.Options options = new PushRefTypePojo.Options(workOrderEntity.getAppId(), workOrderEntity.getMenuId(), workOrderEntity.getFormId(), workOrderEntity.getId(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_ORDER.getCode());
        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserIds, Collections.singletonList(workOrderId), 0, null, I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_ROLLBACK_TITLE), pushMsg, null, options);
        baseProducer.sendMessage(PushTypeEnum.WORKORDER_ROLLBACK, messageRabbitMqDTO);

    }

    private void close(ChangeWorkflowDTO changeWorkflowDTO, WorkOrderFlowNodeEntity nowNodeEntity, WorkOrderEntity workOrderEntity) throws XbbException {
        String corpid = changeWorkflowDTO.getCorpid();
        Long workOrderId = workOrderEntity.getId();
        Long currentTime = DateTimeUtil.getInt();
        if (Objects.isNull(changeWorkflowDTO.getMemo()) || changeWorkflowDTO.getMemo().isEmpty()){
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222044);
        }

        Integer status = workOrderEntity.getStatus();
        if (status.equals(WorkOrderStatusEnum.FINISH.getCode())){
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222032);
        }

//        Long startTime = nowNodeEntity.getStartTime();
        Long endTime = nowNodeEntity.getEndTime();
//        if (startTime == 0L){
//            nowNodeEntity.setStartTime(currentTime);
//        }
        nowNodeEntity.setStatus(WorkOrderNodeStatusEnum.CLOSE.getCode());
        nowNodeEntity.setMemo(changeWorkflowDTO.getMemo());
        if (endTime == 0L){
            nowNodeEntity.setEndTime(currentTime);
            nowNodeEntity.setActualTime((int)(currentTime - nowNodeEntity.getStartTime()));
        }
//        nowNodeEntity.setIsNow(0);
        nowNodeEntity.setEndOperatorName(changeWorkflowDTO.getLoginUser().getName());
        nowNodeEntity.setUpdateTime(currentTime);
        //状态更新
        workOrderFlowNodeModel.update(nowNodeEntity);

        Long flowStartTime = workOrderEntity.getStartTime();
        if (flowStartTime == 0L){
            workOrderEntity.setStartTime(currentTime);
        }
        workOrderEntity.setStatus(WorkOrderStatusEnum.CLOSE.getCode());
//        workOrderEntity.setEndTime(currentTime);
        workOrderEntity.setCloseTime(currentTime);
        workOrderEntity.setUpdateTime(currentTime);
        workOrderEntity.setActualTime((int)(currentTime - workOrderEntity.getStartTime()));
        workOrderEntity.setType(WorkOrderTypeEnum.NORMAL.getCode());
        JSONObject data = workOrderEntity.getData();
        data.put(WorkOrderEnum.NODE_STATUS.getAttr(), WorkOrderNodeStatusEnum.CLOSE.getCode());
        //阶段名称
        if (!Objects.equals(nowNodeEntity.getStageName(), "") && nowNodeEntity.getStageName() != null) {
            data.put(WorkOrderEnum.STAGE_NAME.getAttr(), nowNodeEntity.getStageName());
        }
        workOrderEntity.setData(data);
        workOrderModel.update(workOrderEntity);
//        UserEntity userEntity = new UserEntity();
//        BeanUtil.copyProperties(changeWorkflowDTO.getLoginUser(),userEntity);
//        workOrderFlowNodeModel.save(createCloseNode(workOrderId,userEntity, changeWorkflowDTO.getMemo()));

        //工单关闭消息推送
        UserVO loginUser = changeWorkflowDTO.getLoginUser();
        List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.WORKORDER_CLOSE.getCode(), PushTypeEnum.WORKORDER_CLOSE.getSubCode(), loginUser, workOrderEntity);
        PushRefTypePojo.Options options = new PushRefTypePojo.Options(workOrderEntity.getAppId(), workOrderEntity.getMenuId(), workOrderEntity.getFormId(), workOrderEntity.getId(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_ORDER.getCode());
        String pushMsg = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_CLOSED), workOrderEntity.getSerialNo(), loginUser.getName());

        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(workOrderId), 0, null, I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_CLOSE_TITLE), pushMsg, null, options);
        baseProducer.sendMessage(PushTypeEnum.WORKORDER_CLOSE, messageRabbitMqDTO);

    }

    private void complete(ChangeWorkflowDTO changeWorkflowDTO, WorkOrderFlowNodeEntity nowNodeEntity, WorkOrderEntity workOrderEntity) throws XbbException {
        String corpid = workOrderEntity.getCorpid();
        Long workOrderId = workOrderEntity.getId();
        Long templateId = workOrderEntity.getTemplateId();
        Long currentTime = DateTimeUtil.getInt();
        boolean flag;
        WorkOrderStageEntity workOrderStageEntity;
        boolean isFree;
        boolean isRob = false;
        flag = nowNodeEntity.getStatus().equals(WorkOrderNodeStatusEnum.ONGOING.getCode());
        if (!flag){
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222015);
        }
        Integer actualTime = (int)(currentTime - nowNodeEntity.getStartTime());
        nowNodeEntity.setEndTime(currentTime);
        nowNodeEntity.setActualTime(actualTime);
        nowNodeEntity.setMemo(changeWorkflowDTO.getMemo());
        nowNodeEntity.setStatus(WorkOrderNodeStatusEnum.FINISH.getCode());
//        workOrderFlowNodeModel.save(nowNodeEntity);

        Long stageId = nowNodeEntity.getStageId();
        workOrderStageEntity = workOrderStageModel.getByKey(stageId,corpid);
        WorkOrderTemplateEntity workOrderTemplateEntity = workOrderTemplateModel.getBykey(templateId,corpid);
        isFree = workOrderTemplateEntity.getIsFree() == 1;
        WorkOrderFlowNodeEntity workOrderFlowNodeEntity = new WorkOrderFlowNodeEntity();
        WorkOrderStageEntity nextStage = new WorkOrderStageEntity();

        //下一个节点需要推送的人员id
        Set<String> nextPushIdList = new HashSet<>();
        if (!isFree && !Objects.equals(workOrderStageEntity.getIsLast(),1)){
            nextStage = workOrderStageService.getNextStage(templateId,stageId,corpid);
            if (Objects.equals(nextStage, null)) {
                throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222066, WorkOrderErrorCodeEnum.API_ERROR_222066.getMsg());
            }
            workOrderFlowNodeEntity = new WorkOrderFlowNodeEntity();
            //前端选中的负责人, 指定流程负责人可以在完成时修改
            ReturnUserAndDepartmentPojo user = changeWorkflowDTO.getUser();
            if (Objects.nonNull(user)) {
                String selectUserId = (String) user.getId();
                if (Objects.nonNull(selectUserId)) {
                    UserEntity userEntity = userModel.getByKey(selectUserId, corpid);
                    if (userEntity == null) {
                        throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222063, WorkOrderErrorCodeEnum.API_ERROR_222063.getMsg());
                    }
                    workOrderFlowNodeEntity = createNormalNode(workOrderId,nextStage.getExpectedTime(),userEntity,nextStage);
                    isRob = false;
                    nextPushIdList.add(selectUserId);
                } else {
                    CreateNodeReturnPojo createNodeReturnPojo = createNode(workOrderEntity,workOrderTemplateEntity,nextStage);
                    workOrderFlowNodeEntity = createNodeReturnPojo.getWorkOrderFlowNodeEntity();
                    isRob = createNodeReturnPojo.getIsRob();
                    nextPushIdList = createNodeReturnPojo.getPushIdList();
                }
            } else {
                throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222067, WorkOrderErrorCodeEnum.API_ERROR_222067.getMsg());
            }

            workOrderFlowNodeModel.save(workOrderFlowNodeEntity);
            nowNodeEntity.setIsNow(0);
            workOrderEntity.setNowStageId(workOrderFlowNodeEntity.getStageId());
            if (Objects.equals(workOrderFlowNodeEntity.getNodeType(), WorkOrderFlowNodeTypeEnum.ROB_NODE.getCode())) {
                workOrderEntity.setType(WorkOrderTypeEnum.ROB.getCode());
            }
            //更新团队
            List<String> coUser = new ArrayList<>();
            List<Object> idList = ProSaveHelp.getIdList(JSONArray.parseArray(JSON.toJSONString(changeWorkflowDTO.getCoUser())));
            for (Object id : idList) {
                coUser.add((String) id);
            }
            workOrderFlowUserService.changeTeamInFlow(workOrderFlowNodeEntity.getUserId(), coUser, corpid, workOrderId);

        } else {
            workOrderEntity.setStatus(WorkOrderStatusEnum.FINISH.getCode());
            workOrderEntity.setActualTime((int)(currentTime - workOrderEntity.getStartTime()));
            workOrderEntity.setEndTime(currentTime);
            workOrderEntity.setUpdateTime(currentTime);
        }
        nowNodeEntity.setEndOperatorName(Objects.equals(nowNodeEntity.getUserId(),changeWorkflowDTO.getUserId()) ? "" : changeWorkflowDTO.getLoginUserName());
        JSONObject data = workOrderEntity.getData();
        //指定流程抢单，是否是最后阶段，不是最后阶段完成应为待接受
        if (!isFree && !Objects.equals(workOrderStageEntity.getIsLast(),1)){
            data.put(WorkOrderEnum.NODE_STATUS.getAttr(), workOrderFlowNodeEntity.getStatus());
        } else {
            data.put(WorkOrderEnum.NODE_STATUS.getAttr(), WorkOrderStatusEnum.FINISH.getCode());
        }
        //阶段名称
        if (!isFree && !Objects.equals(workOrderStageEntity.getIsLast(),1)){
            if (!Objects.equals(nextStage.getName(), "") && nextStage.getName() != null) {
                data.put(WorkOrderEnum.STAGE_NAME.getAttr(), nextStage.getName());
            }
        } else if (!isFree && Objects.equals(workOrderStageEntity.getIsLast(),1)){
            if (!Objects.equals(nowNodeEntity.getStageName(), "") && nowNodeEntity.getStageName() != null) {
                data.put(WorkOrderEnum.STAGE_NAME.getAttr(), nowNodeEntity.getStageName());
            }
        }
        workOrderEntity.setData(data);
        workOrderModel.update(workOrderEntity);
        workOrderFlowNodeModel.save(nowNodeEntity);

        //工单完成消息推送
        UserVO loginUser = changeWorkflowDTO.getLoginUser();
        String title;
        String pushMsg;
        List<String> pushUserIds;
        PushRefTypePojo.Options options = new PushRefTypePojo.Options(workOrderEntity.getAppId(), workOrderEntity.getMenuId(), workOrderEntity.getFormId(), workOrderId, SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_ORDER.getCode());

        MessageRabbitMqDTO messageRabbitMqDTO;
        if (!isFree && !Objects.equals(workOrderStageEntity.getIsLast(), 1)) {
            //阶段完成
            title = I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_STAGE_COMPLETE_TITLE);
            pushMsg = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_STAGE_FINISHED), loginUser.getName(), workOrderEntity.getSerialNo(), workOrderStageEntity.getName());
            pushUserIds = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.WORKORDER_STAGE_COMPLETE.getCode(), PushTypeEnum.WORKORDER_STAGE_COMPLETE.getSubCode(), loginUser, workOrderEntity);
            messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserIds, Collections.singletonList(workOrderId), 0, null, title, pushMsg, null, options);
            baseProducer.sendMessage(PushTypeEnum.WORKORDER_STAGE_COMPLETE, messageRabbitMqDTO);

            if (isRob) {
                //流转到下一个节点的时候如果为抢单节点，需要抢单推送
                PushRefTypePojo.Options nextOptions = new PushRefTypePojo.Options(workOrderEntity.getAppId(), workOrderEntity.getMenuId(), workOrderEntity.getFormId(), workOrderEntity.getId(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_ORDER.getCode());
                MessageRabbitMqDTO nextMessageRabbitMqDTO = new MessageRabbitMqDTO(corpid, new ArrayList<>(nextPushIdList), Collections.singletonList(workOrderId), 0, DateTimeUtil.getInt(), I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_WAIT_ROB_TITLE), String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_TO_ROB), workOrderEntity.getSerialNo(), nextStage.getName()), null, nextOptions);
                baseProducer.sendMessage(PushTypeEnum.WORKORDER_PUSH, nextMessageRabbitMqDTO);
            }

        } else {
            //工单整体完成
            title = I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_COMPLETE_TITLE);
            pushMsg = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_FINISHED), loginUser.getName(), workOrderEntity.getSerialNo());
            pushUserIds = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.WORKORDER_COMPLETE.getCode(), PushTypeEnum.WORKORDER_COMPLETE.getSubCode(), loginUser, workOrderEntity);
            messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserIds, Collections.singletonList(workOrderId), 0, null, title, pushMsg, null, options);
            baseProducer.sendMessage(PushTypeEnum.WORKORDER_COMPLETE, messageRabbitMqDTO);

            //工单整体完成外部评价发送短信
            JSONObject scopeRule = JSONObject.parseObject(workOrderTemplateEntity.getScopeRule());
            if (!Objects.isNull(scopeRule) && Objects.equals(scopeRule.getInteger("inside"),0)) {
                WorkOrderEvaluateEntity workOrderEvaluateEntity = workOrderEvaluateModel.getByWorkOrderId(workOrderId, corpid);
                if (Objects.isNull(workOrderEvaluateEntity) || workOrderEvaluateEntity.getRateContent().isEmpty()) {
                    String url = proBaseConfig.getPushFrontUrl() + "index.html?corpid=" + corpid + "&appid=" + Env.DING_XBB_APP_ID + "&dd_nav_bgcolor=ffff943e#/detail/work-order-set-evaluate?dataId=" + workOrderEntity.getId() + "&inside=0&corpid=" + corpid;

                    String requestUrl = "http://u.xbongbong.cn/api/v2/action/shorten_bulk?key=0741ee8f58d58d42bc2c89a2502ff1";

                    JSONObject links = new JSONObject();
                    links.put("url", url);
                    JSONArray linksArray = new JSONArray();
                    linksArray.add(links);
                    JSONObject urlBody = new JSONObject();
                    urlBody.put("links", linksArray);
                    JSONObject body = new JSONObject();
                    body.put("data", urlBody.toJSONString());
                    Map<String, String> headers = new HashMap<>();
                    headers.put("Content-Type", "application/json");
                    JSONObject response = OkHttpUtil.post(requestUrl, (Object) body, headers);

                    if (Objects.nonNull(response)) {
                        XbbShortUrlResponse xbbShortUrlResponse = JSONObject.parseObject(response.toJSONString(), XbbShortUrlResponse.class);

                        if (Objects.nonNull(xbbShortUrlResponse)) {
                            List<XbbShortUrlResponse.Result.ShortenedLinks> shortenedLinks = xbbShortUrlResponse.getResult().getShortenedLinks();

                            XbbShortUrlResponse.Result.ShortenedLinks shortLinks = shortenedLinks.get(0);
                            String shortenUrl = shortLinks.getShortUrl();

                            if (Objects.nonNull(shortenUrl)) {
                                List<SmsReceiverPojo> sendData = new ArrayList<>();
                                // 接收评价短信的电话号码，是工单“联系方式”，如果“联系方式”不存在，则取“关联联系人”的联系方式, 如果电话号码有多个，随机取一个，默认第一个，只发送一条短信
                                JSONObject dataObj = workOrderEntity.getData();
                                JSONArray contactInfoArray = dataObj.getJSONArray(WorkOrderEnum.CONTACT_INFORMATION.getAttr());
                                String phone = null;
                                if (Objects.nonNull(contactInfoArray) && contactInfoArray.size() > 0) {
                                    JSONObject contactInfo = contactInfoArray.getJSONObject(0);
                                    phone = contactInfo.getString("text_2");
                                }
                                if (Objects.isNull(phone)) {
                                    Long contactId = dataObj.getLong(WorkOrderEnum.LINK_CONTACT.getAttr());
                                    if (Objects.nonNull(contactId)){
                                        ContactEntityExt contactEntityExt = contactModel.getByKey(contactId, corpid);
                                        if (Objects.nonNull(contactEntityExt) && contactEntityExt.getDel() == 0) {
                                            JSONObject contactData = contactEntityExt.getData();
                                            JSONArray phoneArray = contactData.getJSONArray(ContactEnum.PHONE.getAttr());
                                            if (Objects.nonNull(phoneArray) && phoneArray.size() > 0) {
                                                JSONObject phoneObject = phoneArray.getJSONObject(0);
                                                phone = phoneObject.getString("text_2");
                                            }
                                        }
                                    }
                                }

                                if (Objects.nonNull(phone)) {
                                    SmsReceiverPojo smsReceiverPojo = new SmsReceiverPojo("", phone, workOrderEntity.getId(), XbbRefTypeEnum.WORK_ORDER.getCode(),
                                            workOrderEntity.getAppId(), workOrderEntity.getMenuId(), workOrderEntity.getFormId(), SaasMarkEnum.SAAS.getCode());
                                    sendData.add(smsReceiverPojo);
                                    String content = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.SMS_SEND_EVAULATE), workOrderTemplateEntity.getName(), nowNodeEntity.getUserName(), shortenUrl);
                                    // 因为工单短信包含链接，归属到营销短信
                                    SmsRabbitMqDTO smsRabbitMqDTO = new SmsRabbitMqDTO(changeWorkflowDTO.getLoginUser().getCorpid(), changeWorkflowDTO.getLoginUser().getUserId(), SmsSendTypeEnum.AT_ONCE.getCode(), content, SmsTemplateSendApiEnum.SPACE_IMAGINATION_NOTICE_AMOUNT.getCode(), null, sendData, XbbRefTypeEnum.WORK_ORDER.getCode(), Arrays.asList(workOrderId), null);
                                    smsProducer.sendSms(SmsSendFromTypeEnum.SMS_SEND, smsRabbitMqDTO);
                                }
                            }
                        }
                    }


//                    JSONObject body = new JSONObject();
//                    body.put("Url", url);
//                    body.put("TermOfValidity", "1-year");
//                    Map<String, String> headers = new HashMap<>();
//                    headers.put("Content-Type", "application/json");
//                    headers.put("Token", "70bbde11ebbd8cfc1aebfa57871d0b1c");
//                    JSONObject response = OkHttpUtil.post("https://dwz.cn/admin/v2/create", (Object) body, headers);
//
//                    LOG.info("shortLink------sms------："+ response);
//                    if (Objects.nonNull(response)) {
//                        ShortUrlResponse shortUrlResponse = JSONObject.parseObject(response.toJSONString(), ShortUrlResponse.class);
//                        if (Objects.nonNull(shortUrlResponse) && Objects.equals(shortUrlResponse.getCode(), 0)) {
//                            String shortenUrl = shortUrlResponse.getShortUrl();
//                            List<SmsReceiverPojo> sendData = new ArrayList<>();
//                            // 接收评价短信的电话号码，是工单“联系方式”，如果“联系方式”不存在，则取“关联联系人”的联系方式, 如果电话号码有多个，随机取一个，默认第一个，只发送一条短信
//                            JSONObject dataObj = workOrderEntity.getData();
//                            JSONArray contactInfoArray = dataObj.getJSONArray(WorkOrderEnum.CONTACT_INFORMATION.getAttr());
//                            String phone = null;
//                            if (Objects.nonNull(contactInfoArray) && contactInfoArray.size() > 0) {
//                                JSONObject contactInfo = contactInfoArray.getJSONObject(0);
//                                phone = contactInfo.getString("text_2");
//                            }
//                            if (Objects.isNull(phone)) {
//                                Long contactId = dataObj.getLong(WorkOrderEnum.LINK_CONTACT.getAttr());
//                                if (Objects.nonNull(contactId)){
//                                    ContactEntityExt contactEntityExt = contactModel.getByKey(contactId, corpid);
//                                    if (Objects.nonNull(contactEntityExt) && contactEntityExt.getDel() == 0) {
//                                        JSONObject contactData = contactEntityExt.getData();
//                                        JSONArray phoneArray = contactData.getJSONArray(ContactEnum.PHONE.getAttr());
//                                        if (Objects.nonNull(phoneArray) && phoneArray.size() > 0) {
//                                            JSONObject phoneObject = phoneArray.getJSONObject(0);
//                                            phone = phoneObject.getString("text_2");
//                                        }
//                                    }
//                                }
//                            }
//
//                            if (Objects.nonNull(phone)) {
//                                SmsReceiverPojo smsReceiverPojo = new SmsReceiverPojo();
//                                smsReceiverPojo.setName("");
//                                smsReceiverPojo.setPhone(phone);
//                                smsReceiverPojo.setRefId(workOrderEntity.getId());
//                                smsReceiverPojo.setRefType(XbbRefTypeEnum.WORK_ORDER.getCode());
//                                smsReceiverPojo.setAppId(workOrderEntity.getAppId());
//                                smsReceiverPojo.setMenuId(workOrderEntity.getMenuId());
//                                smsReceiverPojo.setFormId(workOrderEntity.getFormId());
//                                smsReceiverPojo.setSaasMark(1);
//                                sendData.add(smsReceiverPojo);
//                                String content = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.SMS_SEND_EVAULATE), workOrderTemplateEntity.getName(), nowNodeEntity.getUserName(), shortenUrl);
//                                // 因为工单短信包含链接，归属到营销短信
//                                SmsRabbitMqDTO smsRabbitMqDTO = new SmsRabbitMqDTO(changeWorkflowDTO.getLoginUser().getCorpid(), changeWorkflowDTO.getLoginUser().getUserId(), SmsSendTypeEnum.AT_ONCE.getCode(), content, SmsTemplateSendApiEnum.SPACE_IMAGINATION_NOTICE_AMOUNT.getCode(), null, sendData, XbbRefTypeEnum.WORK_ORDER.getCode(), Arrays.asList(workOrderId), null);
//                                smsProducer.sendSms(SmsSendFromTypeEnum.SMS_SEND, smsRabbitMqDTO);
//                            }
//                        }
//                    }
                }

            }
        }
    }

    private void accept(ChangeWorkflowDTO changeWorkflowDTO, WorkOrderFlowNodeEntity nowNodeEntity, WorkOrderEntity workOrderEntity) throws XbbException {
        Long workOrderId = workOrderEntity.getId();
        String corpid = workOrderEntity.getCorpid();
        Long currentTime = DateTimeUtil.getInt();
        boolean flag = nowNodeEntity.getStatus().equals(WorkOrderNodeStatusEnum.UNACCEPTED.getCode());
        if (!flag){
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222015);
        }
        //当前阶段信息
        WorkOrderStageEntity workOrderStageEntity = workOrderStageModel.getByKey(nowNodeEntity.getStageId(),corpid);
        Integer robType = nowNodeEntity.getRobType();
        UserVO loginUser = changeWorkflowDTO.getLoginUser();
        //老板、超管等最高权限人员
        boolean isBoss = loginUser.isAdminOrBoss();
        //工单主管
        boolean isWorkOrderManager = false;
        for (RoleSimpleVO roleSimpleVO : loginUser.getRoleSet()) {
            if (Objects.equals(roleSimpleVO.getId(), RoleEnum.WORKORDER_MANAGER.getCode())) {
                isWorkOrderManager = true;
                break;
            }
        }
        if (Objects.equals(robType, WorkOrderFlowNodeTypeEnum.NORMAL_NODE.getCode())) {
            // 正常节点，不是当前节点的人不能操作，工单主管和超管除外
            if (!(isBoss || isWorkOrderManager || Objects.equals(loginUser.getUserId(), nowNodeEntity.getUserId()))) {
                throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222015);
            }
        } else if (Objects.equals(robType,WorkOrderFlowNodeTypeEnum.ROB_NODE.getCode())) {
            // 抢单节点,判断有没有人抢单，如果已经被抢不能操作，高级权限
            List<String> accepteUserIds = new ArrayList<>();
            if (Objects.nonNull(workOrderStageEntity)) {
                WorkOrderStageRuleEnum workOrderStageRuleEnum = WorkOrderStageRuleEnum.getByCode(workOrderStageEntity.getRuleId());
                WorkOrderStageRobTypeEnum workOrderStageRobTypeEnum = WorkOrderStageRobTypeEnum.getByCode(workOrderStageEntity.getRefRobType());
                switch (workOrderStageRuleEnum) {
                    case ROB:
                        switch (workOrderStageRobTypeEnum) {
                            case USER:
                                break;
                            case SERVICE:
                                accepteUserIds.addAll(getServiceUserIdList(corpid, workOrderStageEntity.getRefRobId()));
                                break;
                            case DEPARTMENT:
                                accepteUserIds.addAll(getDepartmentUserIdList(corpid, workOrderStageEntity.getRefRobId()));
                                break;
                            default:
                                break;
                        }
                        break;
                    default:
                        break;
                }
            }
            String nodeUserId = nowNodeEntity.getUserId();

            WorkOrderFlowNodeEntity preNodeEntity;
            Map<String,Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("corpid",corpid);
            params.put("workOrderId",workOrderId);
            params.put("nowSort",nowNodeEntity.getSort());
            params.put("del",0);
            preNodeEntity = workOrderFlowNodeModel.getPrevNode(params);
            //如果上一节点是回退的特殊情况
            if (!Objects.isNull(preNodeEntity) && Objects.equals(preNodeEntity.getStatus(), WorkOrderNodeStatusEnum.ROLLBACK.getCode())) {
                if (!(Objects.equals(loginUser.getUserId(), nodeUserId) || isBoss || isWorkOrderManager)) {
                    throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222015);
                }
            } else {
                if (StringUtil.isEmpty(nodeUserId)) {
                    if (!(accepteUserIds.contains(loginUser.getUserId()) || isBoss || isWorkOrderManager)) {
                        throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222015);
                    }
                } else if (!(Objects.equals(loginUser.getUserId(), nodeUserId) || isBoss || isWorkOrderManager)) {
                    throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222015);
                }
            }
        }
        //自由指派第一节点或指定流程第一阶段第一节点
        boolean isFirst;
        boolean isFree = false;
        WorkOrderTemplateEntity workOrderTemplateEntity = workOrderTemplateModel.getBykey(workOrderEntity.getTemplateId(), corpid);
        if (Objects.equals(workOrderTemplateEntity.getIsFree(), 1)) {
            isFree = true;
        } else {
            isFree = false;
        }

        String stageName = "";
        if (Objects.isNull(workOrderStageEntity)){
            isFirst = nowNodeEntity.getSort().equals(0);
        } else {
            isFirst = workOrderStageEntity.getSort().equals(0) && nowNodeEntity.getSort().equals(0);
            stageName = workOrderStageEntity.getName();
        }
        if (isFirst) {
            if (workOrderEntity.getStartTime() == null || workOrderEntity.getStartTime() == 0){
                workOrderEntity.setStartTime(currentTime);
            }
        }
        nowNodeEntity.setStatus(WorkOrderNodeStatusEnum.ONGOING.getCode());
        nowNodeEntity.setStartTime(currentTime);
        nowNodeEntity.setUpdateTime(currentTime);
        if (Objects.equals(nowNodeEntity.getNodeType(), WorkOrderFlowNodeTypeEnum.ROB_NODE.getCode())){
            nowNodeEntity.setUserId(changeWorkflowDTO.getUserId());
            nowNodeEntity.setUserName(changeWorkflowDTO.getLoginUserName());
            nowNodeEntity.setUserAvatar(loginUser.getAvatar());
            nowNodeEntity.setNodeType(0);
            workOrderFlowUserService.createNewMain(workOrderId, corpid, changeWorkflowDTO.getUserId());
        } else {
            nowNodeEntity.setStartOperatorName(Objects.equals(nowNodeEntity.getUserId(),changeWorkflowDTO.getUserId()) ? "" : changeWorkflowDTO.getLoginUserName());
        }

        //之前如果是关闭过该工单，则需要重置startTime
        if (workOrderEntity.getStartTime() == null || workOrderEntity.getStartTime() == 0) {
            workOrderEntity.setStartTime(currentTime);
        }

        //节点更新,已接收
        workOrderFlowNodeModel.update(nowNodeEntity);
        workOrderEntity.setUpdateTime(currentTime);
        //工作流更新,已接收
        workOrderEntity.setType(WorkOrderTypeEnum.NORMAL.getCode());
        workOrderEntity.setStatus(WorkOrderStatusEnum.ONGOING.getCode());
        JSONObject data = workOrderEntity.getData();
        data.put(WorkOrderEnum.NODE_STATUS.getAttr(), WorkOrderStatusEnum.ONGOING.getCode());
        //阶段名称
        if (!Objects.equals(stageName, "") && stageName != null) {
            data.put(WorkOrderEnum.STAGE_NAME.getAttr(), stageName);
        }
        workOrderEntity.setData(data);
        workOrderModel.update(workOrderEntity);

        // 工单负责人接收工单消息
        List<String> pushUserIds = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.WORKORDER_CONFIRM.getCode(), PushTypeEnum.WORKORDER_CONFIRM.getSubCode(), loginUser, workOrderEntity);
        String pushMsg;
        if (isFree) {
            pushMsg = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_ACCEPTED_FREE), loginUser.getName(), workOrderEntity.getSerialNo());
        } else {
            pushMsg = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_ACCEPTED), loginUser.getName(), workOrderEntity.getSerialNo(), workOrderStageEntity.getName());
        }
        PushRefTypePojo.Options options = new PushRefTypePojo.Options(workOrderEntity.getAppId(), workOrderEntity.getMenuId(), workOrderEntity.getFormId(), workOrderEntity.getId(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WORK_ORDER.getCode());
        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserIds, Collections.singletonList(workOrderId), 0, null, I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_ACCEPT_TITLE), pushMsg, null, options);
        baseProducer.sendMessage(PushTypeEnum.WORKORDER_CONFIRM, messageRabbitMqDTO);


    }

    /**
     * 新建回退节点
     * @param workOrderFlowNodeEntity
     */
    private WorkOrderFlowNodeEntity createRollbackNode(WorkOrderFlowNodeEntity workOrderFlowNodeEntity) {
        workOrderFlowNodeEntity.setStatus(WorkOrderNodeStatusEnum.UNACCEPTED.getCode());
        workOrderFlowNodeEntity.setId(null);
        Integer maxSort = getMaxSort(workOrderFlowNodeEntity.getWorkOrderId(),workOrderFlowNodeEntity.getStageId(),workOrderFlowNodeEntity.getCorpid());
        workOrderFlowNodeEntity.setSort(maxSort);
        workOrderFlowNodeEntity.setIsNow(1);
        workOrderFlowNodeEntity.setExpectedTime(workOrderFlowNodeEntity.getExpectedTime());
        workOrderFlowNodeEntity.setActualTime(0);
        workOrderFlowNodeEntity.setStartTime(0L);
        workOrderFlowNodeEntity.setEndTime(0L);
        workOrderFlowNodeEntity.setSourceId(0L);
        workOrderFlowNodeEntity.setMemo("");
        return workOrderFlowNodeEntity;
    }

    /**
     * 创建重启节点
     * @param workOrderFlowNodeEntity
     */
    private WorkOrderFlowNodeEntity createRestartNode(WorkOrderFlowNodeEntity workOrderFlowNodeEntity) throws XbbException{
        workOrderFlowNodeEntity.setId(null);
        workOrderFlowNodeEntity.setStatus(WorkOrderNodeStatusEnum.UNACCEPTED.getCode());
        Integer maxSort = getMaxSort(workOrderFlowNodeEntity.getWorkOrderId(),workOrderFlowNodeEntity.getStageId(),workOrderFlowNodeEntity.getCorpid());
        workOrderFlowNodeEntity.setSort(maxSort);
        workOrderFlowNodeEntity.setIsNow(1);
        workOrderFlowNodeEntity.setExpectedTime(workOrderFlowNodeEntity.getExpectedTime());
        workOrderFlowNodeEntity.setActualTime(0);
        workOrderFlowNodeEntity.setStartTime(0L);
        workOrderFlowNodeEntity.setEndTime(0L);
        workOrderFlowNodeEntity.setMemo("");
        return workOrderFlowNodeEntity;
    }

    /**
     * 创建关闭节点
     * @param workOrderId
     * @param userEntity
     * @param memo
     * @throws XbbException
     */
    private WorkOrderFlowNodeEntity createCloseNode(Long workOrderId, UserEntity userEntity, String memo) throws XbbException{
        WorkOrderFlowNodeEntity workOrderFlowNodeEntity = new WorkOrderFlowNodeEntity();
        workOrderFlowNodeEntity.setCorpid(userEntity.getCorpid());
        workOrderFlowNodeEntity.setWorkOrderId(workOrderId);
        workOrderFlowNodeEntity.setUserId(userEntity.getUserId());
        workOrderFlowNodeEntity.setUserAvatar(userEntity.getAvatar());
        workOrderFlowNodeEntity.setUserName(userEntity.getName());
        workOrderFlowNodeEntity.setStatus(WorkOrderNodeStatusEnum.CLOSE.getCode());
        workOrderFlowNodeEntity.setSort(0);
        workOrderFlowNodeEntity.setIsNow(1);
        workOrderFlowNodeEntity.setExpectedTime(0);
        workOrderFlowNodeEntity.setActualTime(0);
        workOrderFlowNodeEntity.setStartTime(DateTimeUtil.getInt());
        workOrderFlowNodeEntity.setEndTime(DateTimeUtil.getInt());
        workOrderFlowNodeEntity.setMemo(memo);
        return workOrderFlowNodeEntity;

    }

    @Override
    public List<FieldAttrEntity> completeItem(Long workOrderId, String corpid) throws XbbException {
        WorkOrderEntity workOrderEntity = workOrderModel.getByKey(workOrderId,corpid);
        if (Objects.isNull(workOrderEntity) || Objects.equals(workOrderEntity.getDel(), DelEnum.DELETE.getDel())) {
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222011);
        }
        Long templateId = workOrderEntity.getTemplateId();
        WorkOrderTemplateEntity workOrderTemplateEntity = workOrderTemplateModel.getBykey(templateId,corpid);
        boolean isFree = workOrderTemplateEntity.getIsFree() == 1;
        FieldAttrEntity memoEntity = new FieldAttrEntity();
        memoEntity.setAttr("memo");
        memoEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.COMPLETE_NOTE));
        memoEntity.setFieldType(FieldTypeEnum.TEXTAREA.getType());
        memoEntity.setEditable(1);
        memoEntity.setRequired(0);
        memoEntity.setVisible(1);
        memoEntity.setDefaultAttr(new DefaultAttrPoJo());
        if (isFree) {
            return Collections.singletonList(memoEntity);
        } else {
            List<WorkOrderFlowNodeEntity> workOrderFlowNodeEntityList = workOrderFlowNodeModel.getNode(workOrderId,1,corpid);
            WorkOrderFlowNodeEntity nowNodeEntity = workOrderFlowNodeEntityList.get(0);
            WorkOrderStageEntity workOrderStageEntity = workOrderStageService.getNextStage(workOrderEntity.getTemplateId(), nowNodeEntity.getStageId(),corpid);
            FieldAttrEntity stageEntity = new FieldAttrEntity();
            stageEntity.setAttr("stage");
            stageEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.NEXT_STAGE));
            DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
            defaultAttrPoJo.setDefaultValue(Objects.isNull(workOrderStageEntity) ? WorkOrderStageOperationEnum.COMPLETE.getName() : workOrderStageEntity.getName());
            stageEntity.setDefaultAttr(defaultAttrPoJo);
            stageEntity.setFieldType(FieldTypeEnum.TEXT.getType());
            stageEntity.setEditable(0);
            stageEntity.setRequired(0);
            stageEntity.setVisible(1);
            if (Objects.isNull(workOrderStageEntity)) {
                return Arrays.asList(stageEntity,memoEntity);
            } else {
                boolean isRob = Objects.equals(workOrderStageEntity.getRuleId(),WorkOrderStageRuleEnum.ROB.getCode());
                String nowUserId = "";
                FieldAttrEntity userEntity = new FieldAttrEntity();
                userEntity.setAttr("user");
                userEntity.setAttrName(I18nMessageUtil.getMessage(CommonConstant.MAIN_USER));
                userEntity.setRequired(1);
                userEntity.setVisible(1);
                if (isRob){
                    userEntity.setEditable(0);
                    userEntity.setFieldType(FieldTypeEnum.TEXT.getType());
                    DefaultAttrPoJo userDefaultAttrPoJo = new DefaultAttrPoJo();
                    String robName = workOrderStageEntity.getRefRobName();
                    userDefaultAttrPoJo.setDefaultValue(robName + WorkOrderStageRobTypeEnum.getByCode(workOrderStageEntity.getRefRobType()).getName());
                    userDefaultAttrPoJo.setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
                    userEntity.setDefaultAttr(userDefaultAttrPoJo);
                } else {
                    CreateNodeReturnPojo createNodeReturnPojo = new CreateNodeReturnPojo();
                    try {
                        createNodeReturnPojo = createNode(workOrderEntity, workOrderTemplateEntity, workOrderStageEntity);
                    } catch (XbbException e) {
                        e.printStackTrace();
                    }
                    WorkOrderFlowNodeEntity workOrderFlowNodeEntity = createNodeReturnPojo.getWorkOrderFlowNodeEntity();
                    userEntity.setEditable(1);
                    userEntity.setFieldType(FieldTypeEnum.USER.getType());
                    DefaultAttrPoJo userDefaultAttrPoJo = new DefaultAttrPoJo();
                    if (Objects.nonNull(workOrderFlowNodeEntity)) {
                        OptionalRangeEntity optionalRangeEntity = new OptionalRangeEntity();
                        optionalRangeEntity.setEditable(1);
                        optionalRangeEntity.setProperty(FieldTypeEnum.USER.getAlias());
                        optionalRangeEntity.setId(workOrderFlowNodeEntity.getUserId());
                        optionalRangeEntity.setName(workOrderFlowNodeEntity.getUserName());
                        userDefaultAttrPoJo.setDefaultList(Collections.singletonList(optionalRangeEntity));
                        userDefaultAttrPoJo.setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
                    }
                    userEntity.setDefaultAttr(userDefaultAttrPoJo);
                    nowUserId = workOrderStageEntity.getRefRobId();
                }
                FieldAttrEntity coUserEntity = new FieldAttrEntity();
                coUserEntity.setAttr("coUser");
                coUserEntity.setAttrName(I18nMessageUtil.getMessage(CommonConstant.COLLABORATOR));
                coUserEntity.setFieldType(FieldTypeEnum.USER_GROUP.getType());
                coUserEntity.setEditable(1);
                coUserEntity.setRequired(0);
                coUserEntity.setVisible(1);
                DefaultAttrPoJo coUserDefaultAttrPoJo = new DefaultAttrPoJo();
                List<WorkOrderFlowUserEntity> workOrderFlowUserEntityList = workOrderFlowUserService.getTeamUserList(workOrderId,corpid);
                List<OptionalRangeEntity> optionalRangeEntityList = new ArrayList<>();
                for (WorkOrderFlowUserEntity workOrderFlowUserEntity : workOrderFlowUserEntityList) {
                    if (!isRob && Objects.equals(workOrderFlowUserEntity.getUserId(),nowUserId)) {
                        continue;
                    }
                    OptionalRangeEntity coOptionalRangeEntity = new OptionalRangeEntity();
                    coOptionalRangeEntity.setEditable(1);
                    coOptionalRangeEntity.setProperty(FieldTypeEnum.USER.getAlias());
                    coOptionalRangeEntity.setId(workOrderFlowUserEntity.getUserId());
                    coOptionalRangeEntity.setName(workOrderFlowUserEntity.getUserName());
                    optionalRangeEntityList.add(coOptionalRangeEntity);
                }
                coUserDefaultAttrPoJo.setDefaultList(optionalRangeEntityList);
                coUserDefaultAttrPoJo.setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
                coUserEntity.setDefaultAttr(coUserDefaultAttrPoJo);
                return Arrays.asList(stageEntity,userEntity,coUserEntity,memoEntity);
            }
        }
    }

    @Override
    public List<FieldAttrEntity> transferItem(Long workOrderId, String corpid) throws XbbException {
        WorkOrderEntity workOrderEntity = workOrderModel.getByKey(workOrderId,corpid);
        if (Objects.isNull(workOrderEntity) || Objects.equals(workOrderEntity.getDel(), DelEnum.DELETE.getDel())) {
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222011);
        }
        Long templateId = workOrderEntity.getTemplateId();
        WorkOrderTemplateEntity workOrderTemplateEntity = workOrderTemplateModel.getBykey(templateId,corpid);
        Boolean isFree = workOrderTemplateEntity.getIsFree() == 1;
        FieldAttrEntity userEntity = new FieldAttrEntity();
        userEntity.setAttr("user");
        userEntity.setAttrName(I18nMessageUtil.getMessage(CommonConstant.MAIN_USER));
        userEntity.setFieldType(FieldTypeEnum.USER.getType());
        userEntity.setEditable(1);
        userEntity.setRequired(1);
        userEntity.setDefaultAttr(new DefaultAttrPoJo());
        userEntity.setVisible(1);
        FieldAttrEntity coUserEntity = new FieldAttrEntity();
        coUserEntity.setAttr("coUser");
        coUserEntity.setAttrName(I18nMessageUtil.getMessage(CommonConstant.COLLABORATOR));
        coUserEntity.setFieldType(FieldTypeEnum.USER_GROUP.getType());
        coUserEntity.setEditable(1);
        coUserEntity.setRequired(0);
        coUserEntity.setVisible(1);
        DefaultAttrPoJo userDefaultAttrPoJo = new DefaultAttrPoJo();
        List<WorkOrderFlowUserEntity> workOrderFlowUserEntityList = workOrderFlowUserService.getTeamUserList(workOrderId,corpid);
        List<OptionalRangeEntity> optionalRangeEntityList = new ArrayList<>();
        for (WorkOrderFlowUserEntity workOrderFlowUserEntity : workOrderFlowUserEntityList){
            OptionalRangeEntity optionalRangeEntity = new OptionalRangeEntity();
            optionalRangeEntity.setEditable(1);
            optionalRangeEntity.setProperty(FieldTypeEnum.USER.getAlias());
            optionalRangeEntity.setId(workOrderFlowUserEntity.getUserId());
            optionalRangeEntity.setName(workOrderFlowUserEntity.getUserName());
            optionalRangeEntityList.add(optionalRangeEntity);
        }
        userDefaultAttrPoJo.setDefaultList(optionalRangeEntityList);
        userDefaultAttrPoJo.setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
        coUserEntity.setDefaultAttr(userDefaultAttrPoJo);
        FieldAttrEntity memoEntity = new FieldAttrEntity();
        memoEntity.setAttr("memo");
        memoEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.TRANSFER_NOTE));
        memoEntity.setFieldType(FieldTypeEnum.TEXTAREA.getType());
        memoEntity.setEditable(1);
        memoEntity.setRequired(0);
        memoEntity.setVisible(1);
        memoEntity.setDefaultAttr(new DefaultAttrPoJo());
        if (isFree){
            return Arrays.asList(userEntity,coUserEntity,memoEntity);
        }else {
            WorkOrderStageEntity workOrderStageEntity = workOrderStageModel.getByKey(workOrderEntity.getNowStageId(),corpid);
            FieldAttrEntity stageEntity = new FieldAttrEntity();
            stageEntity.setAttr("stage");
            stageEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.CURRENT_STAGE));
            stageEntity.setFieldType(FieldTypeEnum.TEXT.getType());
            stageEntity.setEditable(0);
            stageEntity.setRequired(0);
            DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
            defaultAttrPoJo.setDefaultValue(workOrderStageEntity.getName());
            defaultAttrPoJo.setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
            stageEntity.setDefaultAttr(defaultAttrPoJo);
            stageEntity.setVisible(1);
            return Arrays.asList(stageEntity,userEntity,coUserEntity,memoEntity);
        }
    }

    @Override
    public List<FieldAttrEntity> rollbackItem() {
        FieldAttrEntity typeEntity = new FieldAttrEntity();
        typeEntity.setAttr("type");
        typeEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.OPERATE_TYPE));
        typeEntity.setFieldType(FieldTypeEnum.TEXT.getType());
        typeEntity.setEditable(0);
        typeEntity.setRequired(0);
        typeEntity.setVisible(1);
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        defaultAttrPoJo.setDefaultValue(WorkOrderStageOperationEnum.ROLLBACK.getName());
        defaultAttrPoJo.setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
        typeEntity.setDefaultAttr(defaultAttrPoJo);
        FieldAttrEntity memoEntity = new FieldAttrEntity();
        memoEntity.setAttr("memo");
        memoEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.ROLLBACK_REASON));
        memoEntity.setFieldType(FieldTypeEnum.TEXTAREA.getType());
        memoEntity.setEditable(1);
        memoEntity.setRequired(0);
        memoEntity.setVisible(1);
        memoEntity.setDefaultAttr(new DefaultAttrPoJo());
        return Arrays.asList(typeEntity,memoEntity);
    }

    @Override
    public List<FieldAttrEntity> restartItem(Long workOrderId,String corpid) throws XbbException {
        WorkOrderEntity workOrderEntity = workOrderModel.getByKey(workOrderId,corpid);
        if (Objects.isNull(workOrderEntity) || Objects.equals(workOrderEntity.getDel(), DelEnum.DELETE.getDel())) {
            throw new XbbException(WorkOrderErrorCodeEnum.API_ERROR_222011);
        }
        Long templateId = workOrderEntity.getTemplateId();
        WorkOrderTemplateEntity workOrderTemplateEntity = workOrderTemplateModel.getBykey(templateId,corpid);
        Boolean isFree = workOrderTemplateEntity.getIsFree() == 1;
        if (isFree){
            WorkOrderFlowUserEntity mainUserEntity = workOrderFlowUserService.getMainUser(workOrderId,corpid);
            FieldAttrEntity userEntity = new FieldAttrEntity();
            userEntity.setAttr("user");
            userEntity.setAttrName(I18nMessageUtil.getMessage(CommonConstant.MAIN_USER));
            userEntity.setFieldType(FieldTypeEnum.USER.getType());
            userEntity.setEditable(1);
            userEntity.setRequired(1);
            DefaultAttrPoJo userDefaultAttrPoJo = new DefaultAttrPoJo();
            OptionalRangeEntity optionalRangeEntity = new OptionalRangeEntity();
            optionalRangeEntity.setEditable(1);
            optionalRangeEntity.setProperty(FieldTypeEnum.USER.getAlias());
            if (Objects.nonNull(mainUserEntity)) {
                optionalRangeEntity.setId(mainUserEntity.getUserId());
                optionalRangeEntity.setName(mainUserEntity.getUserName());
            }
            userDefaultAttrPoJo.setDefaultList(Collections.singletonList(optionalRangeEntity));
            userDefaultAttrPoJo.setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
            userEntity.setDefaultAttr(userDefaultAttrPoJo);
            userEntity.setVisible(1);
            FieldAttrEntity memoEntity = new FieldAttrEntity();
            memoEntity.setAttr("memo");
            memoEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.RESTART_REASON));
            memoEntity.setFieldType(FieldTypeEnum.TEXTAREA.getType());
            memoEntity.setEditable(1);
            memoEntity.setRequired(1);
            memoEntity.setVisible(1);
            return Arrays.asList(userEntity,memoEntity);
        }else {
            List<WorkOrderStageEntity> workOrderStageEntityList = workOrderStageService.getStageList(templateId,corpid,true);
            FieldAttrEntity stageEntity = new FieldAttrEntity();
            stageEntity.setAttr("nextStageId");
            stageEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.RESTART_STAGE));
            List<ItemPoJo> itemPoJoList = new ArrayList<>();
            for (WorkOrderStageEntity workOrderStageEntity :workOrderStageEntityList){
                ItemPoJo itemPoJo = new ItemPoJo();
                itemPoJo.setValue(workOrderStageEntity.getId());
                itemPoJo.setText(workOrderStageEntity.getName());
                itemPoJoList.add(itemPoJo);
            }
            itemPoJoList.get(0).setChecked(true);
            stageEntity.setItems(itemPoJoList);
            stageEntity.setFieldType(FieldTypeEnum.COMBO.getType());
            stageEntity.setEditable(1);
            stageEntity.setRequired(1);
            stageEntity.setVisible(1);
            stageEntity.setDefaultAttr(new DefaultAttrPoJo());
            stageEntity.setComboType(0);
            FieldAttrEntity memoEntity = new FieldAttrEntity();
            memoEntity.setAttr("memo");
            memoEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.RESTART_REASON));
            memoEntity.setFieldType(FieldTypeEnum.TEXTAREA.getType());
            memoEntity.setEditable(1);
            memoEntity.setRequired(1);
            memoEntity.setVisible(1);
            memoEntity.setDefaultAttr(new DefaultAttrPoJo());
            return Arrays.asList(stageEntity,memoEntity);
        }
    }

    @Override
    public List<FieldAttrEntity> closeItem() {
        FieldAttrEntity typeEntity = new FieldAttrEntity();
        typeEntity.setAttr("type");
        typeEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.OPERATE_TYPE));
        typeEntity.setFieldType(FieldTypeEnum.TEXT.getType());
        typeEntity.setEditable(0);
        typeEntity.setRequired(1);
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        defaultAttrPoJo.setDefaultValue(OperateTypeEnum.CLOSE.getName());
        defaultAttrPoJo.setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
        typeEntity.setDefaultAttr(defaultAttrPoJo);
        typeEntity.setVisible(1);
        FieldAttrEntity memoEntity = new FieldAttrEntity();
        memoEntity.setAttr("memo");
        memoEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.CLOSE_REASON));
        memoEntity.setFieldType(FieldTypeEnum.TEXTAREA.getType());
        memoEntity.setDefaultAttr(new DefaultAttrPoJo());
        memoEntity.setEditable(1);
        memoEntity.setRequired(1);
        memoEntity.setVisible(1);
        return Arrays.asList(typeEntity,memoEntity);
    }

    @Override
    public TimeConsumingOutPojo workOrderConsueTime(WorkOrderEntityExt entity) {
        return commonHelp.workOrderConsueTime(entity);
    }

    @Override
    public TimeConsumingOutPojo appWorkOrderConsueTime(WorkOrderEntityExt entity) {
        return commonHelp.appWorkOrderConsueTime(entity);
    }

    @Override
    public TimeConsumingOutPojo workOrderNodeConsueTime(WorkOrderFlowNodeEntity entity) {
        String consueTimeStr = "";
        Integer expectTime = entity.getExpectedTime();
        Integer status = entity.getStatus();
        Integer isOut = 0;
        TimeConsumingOutPojo timeConsumingOutPojo = new TimeConsumingOutPojo();
        if (Objects.equals(status,WorkOrderNodeStatusEnum.UNACCEPTED.getCode())){
            consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.ESTIMATED_TIME_CONSUMING), TimeUtil.getString(expectTime));
        }else if (Objects.equals(status,WorkOrderNodeStatusEnum.ONGOING.getCode())){
            Integer actualTime = (int)(DateTimeUtil.getInt() - entity.getStartTime());
            if (actualTime > expectTime){
                consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.TIME_OUT),TimeUtil.getString(actualTime - expectTime));
                isOut = 1;
            }else {
                consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.TIME_CONSUMING),TimeUtil.getString(actualTime));
            }
        }else if (Objects.equals(status,WorkOrderNodeStatusEnum.FINISH.getCode()) || Objects.equals(status,WorkOrderNodeStatusEnum.ROLLBACK.getCode()) || Objects.equals(status,WorkOrderNodeStatusEnum.TRANSFERRED.getCode())){
            Integer actualTime = (int)(entity.getEndTime() - entity.getStartTime());
            if (actualTime > expectTime){
                consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.TIME_OUT),TimeUtil.getString(actualTime - expectTime));
                isOut =1;
            }else {
                consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.TIME_CONSUMING),TimeUtil.getString(actualTime));
            }
        } else if (Objects.equals(status, WorkOrderNodeStatusEnum.CLOSE.getCode())) {
            if (Objects.equals(entity.getStartTime(), 0L)) {
                consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.TIME_CONSUMING), TimeUtil.getString(0));
            } else {
                Integer actualTime = (int)(entity.getEndTime() - entity.getStartTime());
                if (actualTime > expectTime){
                    consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.TIME_OUT),TimeUtil.getString(actualTime - expectTime));
                    isOut =1;
                }else {
                    consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.TIME_CONSUMING),TimeUtil.getString(actualTime));
                }
            }
        }
        timeConsumingOutPojo.setConsumeTimeStr(consueTimeStr);
        timeConsumingOutPojo.setIsOut(isOut);
        return timeConsumingOutPojo;
    }

    @Override
    public TimeConsumingOutPojo workOrderSpecialConsueTime(WorkOrderEntityExt entity) {
        String consueTimeStr = "";
        Integer status = entity.getStatus();
        Integer isOut = 0;
        Integer expectTime = entity.getExpectedTime();
        TimeConsumingOutPojo timeConsumingOutPojo = new TimeConsumingOutPojo();
        if (Objects.equals(status,WorkOrderNodeStatusEnum.UNACCEPTED.getCode())){
            consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.ESTIMATED_TIME_CONSUMING), TimeUtil.getString(expectTime));
        }else if (Objects.equals(status,WorkOrderNodeStatusEnum.ONGOING.getCode())){
            Integer actualTime = (int)(DateTimeUtil.getInt() - entity.getStartTime());
            consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.TIME_CONSUMING),TimeUtil.getString(actualTime));
        }else if (Objects.equals(status,WorkOrderNodeStatusEnum.FINISH.getCode()) || Objects.equals(status,WorkOrderNodeStatusEnum.ROLLBACK.getCode()) || Objects.equals(status,WorkOrderNodeStatusEnum.TRANSFERRED.getCode())){
            Integer actualTime = (int)(entity.getEndTime() - entity.getStartTime());
            consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.TIME_CONSUMING),TimeUtil.getString(actualTime));
        } else if (Objects.equals(status, WorkOrderNodeStatusEnum.CLOSE.getCode())) {
            if (Objects.equals(entity.getStartTime(), 0L)) {
                consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.TIME_CONSUMING), TimeUtil.getString(0));
            } else {
                //工单直接关闭，没有结束时间的情况
                if (Objects.equals(entity.getEndTime(), 0L)) {
                    Integer actualTime = (int)(entity.getCloseTime() - entity.getStartTime());
                    consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.TIME_CONSUMING),TimeUtil.getString(actualTime));
                } else {
                    Integer actualTime = (int)(entity.getEndTime() - entity.getStartTime());
                    consueTimeStr = String.format(I18nMessageUtil.getMessage(WorkOrderConsueTimeConstant.TIME_CONSUMING),TimeUtil.getString(actualTime));
                }
            }
        }
        timeConsumingOutPojo.setConsumeTimeStr(consueTimeStr);
        timeConsumingOutPojo.setIsOut(isOut);
        return timeConsumingOutPojo;
    }


    /**
     * 获取最大排序值
     * @param workOrderId
     * @param stageId
     * @param corpid
     * @return
     */
    private Integer getMaxSort(Long workOrderId, Long stageId, String corpid) {
        WorkOrderFlowNodeEntity lastNode = workOrderFlowNodeModel.getLastNode(workOrderId,stageId,corpid);
        Integer maxSort = 0;
        if (Objects.nonNull(lastNode)){
            maxSort = lastNode.getSort() + 1;
        }
        return maxSort;
    }
}
